package cool.mtc.security.auth.jwt;

import cool.mtc.security.SecurityProperties;
import cool.mtc.security.constant.AuthConstant;
import cool.mtc.security.constant.SecurityConstant;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 明河
 */
public class JwtAuthFilter extends AbstractAuthenticationProcessingFilter {

    public JwtAuthFilter(SecurityProperties securityProperties) {
        super(new AntPathRequestMatcher(securityProperties.getAuthJwt().getAntPattern()));
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!super.requiresAuthentication(request, response)) {
            super.doFilter(request, response, chain);
            return;
        }

        Authentication authentication = null;
        AuthenticationException authenticationException = null;
        try {
            authentication = attemptAuthentication(request, response);
        } catch (AuthenticationException ex) {
            authenticationException = ex;
        }

        if (null == authentication) {
            super.unsuccessfulAuthentication(request, response, authenticationException);
            return;
        }
        super.successfulAuthentication(request, response, chain, authentication);
        chain.doFilter(request, response);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        JwtAuthForm form = JwtAuthForm.transForm(request);
        request.setAttribute(SecurityConstant.REQUEST_ATTRIBUTE_KEY_AUTH_FORM, form);
        request.setAttribute(SecurityConstant.REQUEST_ATTRIBUTE_KEY_AUTH_WAY, AuthConstant.AUTH_WAY_JWT);
        JwtAuthToken authToken = new JwtAuthToken(form);
        return super.getAuthenticationManager().authenticate(authToken);
    }
}
